#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <stdint.h>

#include "driver/fs4412_led.h"
#include "driver/fs4412_pwm.h"
#include "waring.h"

// 上限值: 超过声光报警
#define UPPER_LIMIT 2000
// 灯亮的单位: 每 UNIT 亮一个灯
#define UNIT 500
#define MAX_LEDS 5

static int fd_led;
static int fd_pwm;
static int fd_adc;

static void ledAllOff()
{
    int i;
    for (i = 1; i <= MAX_LEDS; i++)
    {
        ioctl(fd_led, LED_OFF, &i);
    }
}

int main(int argc, const char *argv[])
{
    fd_led = open("/dev/led", O_RDWR);
    fd_pwm = open("/dev/pwm", O_RDWR | O_NONBLOCK);
    fd_adc = open("/dev/adc", O_RDWR);
    int headLed = 1;
    int tailLed = MAX_LEDS;
    int i;
    int data;
    int oldData = -1;
    int led_count = 0;

    if (fd_led < 0 || fd_pwm < 0 || fd_adc < 0)
    {
        perror("open");
        exit(1);
    }

    while (1)
    {
        // 应用程序通过read函数访问驱动的read接口，读取ad转换后的值
        // 函数原型int read(int handle, void *buf, int count);
        // data用于存放转换后的数据
        read(fd_adc, &data, sizeof(data));
        // 数据有变化才打印
        if (data != oldData)
        {
            oldData = data;
            // 打印转换后的数据data
            printf("digital data is : %d:\n", data);
        }

        // 判断是否需要报警
        if (data >= UPPER_LIMIT)
        {
            // 报警
            // 可能有正常时亮着的灯,先把灯都关掉
            ledAllOff();
            // 报警就亮第一个和最后一个灯
            ioctl(fd_led, LED_ON, &headLed);
            ioctl(fd_led, LED_ON, &tailLed);
            // 播放报警声
            // 打开pwm定时器，调用函数int ioctl(int fd, int cmd),cmd为PWM_ON
            ioctl(fd_pwm, PWM_ON);
            for (i = 0; i < sizeof(Waring) / sizeof(Note); i++)
            {
                // 分频后的时钟频率/音符脉冲的频率
                int div = (PCLK / 256 / 4) / Waring[i].pitch;
                // 调用函数 int ioctl(int fd,int cmd,char *argp) 设置pwd定时器
                // 的初始值和翻转值，cmd为SET_CNT，把div传入第三个参数
                ioctl(fd_pwm, SET_CNT, &div);
                usleep(Waring[i].dimation * 100);
            }
        }
        else
        {
            // 正常
            // 可能有报警时亮着的灯,先把灯都关掉
            ledAllOff();
            // 可能有报警声,关闭
            ioctl(fd_pwm, PWM_OFF, &div);
            // 亮灯
            led_count = data / UNIT;
            for (i = 1; i <= led_count; i++)
            {
                ioctl(fd_led, LED_ON, &i);
            }
        }
    }
    return 0;
}